#
# Ronin Exploits - A Ruby library for Ronin that provides exploitation and
# payload crafting functionality.
#
# Copyright (c) 2007-2013 Hal Brodigan (postmodern.mod3 at gmail.com)
#
# This file is part of Ronin Exploits.
#
# Ronin is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ronin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ronin.  If not, see <http://www.gnu.org/licenses/>
#

module Ronin
  module Exploits
    #
    # The {Tests} module contains convenience methods to be called when a
    # built {Exploit} is tested.
    #
    module Tests
      #
      # Tests that a target has been selected.
      #
      # @return [true]
      #   Specifies that a target has been selected.
      #
      # @raise [TargetUnspecified]
      #   No suitable target was provided.
      #
      def test_target!
        if target.nil?
          raise(TargetUnspecified,"no suitable target specified")
        end

        return true
      end

      #
      # Tests that the selected target has an arch property.
      #
      # @return [true]
      #   Specifies that an architecture is being targeted by the currently
      #   selected target.
      #
      # @raise [TargetDataMissing]
      #   A valid Arch was expected from the current target.
      #
      def test_arch!
        if arch.nil?
          raise(TargetDataMissing,"no suitable arch was specified")
        end

        return true
      end

      #
      # Tests that the selected target has an os property.
      #
      # @return [true]
      #   Specifies that an OS is being targeted by the currently selected
      #   target.
      #
      # @raise [TargetDataMissing]
      #   A valid OS was expected from the current target.
      #
      def test_os!
        if os.nil?
          raise(TargetDataMissing,"no suitable os was specified")
        end

        return true
      end

      #
      # Tests that the selected target has an software property.
      #
      # @return [true]
      #   Specifies that a piece of software is being targeted by the
      #   currently selected target.
      #
      # @raise [TargetDataMissing]
      #   A valid piece of software was expected from the current target.
      #
      def test_software!
        if software.nil?
          raise(TargetDataMissing,"no suitable software was specified")
        end

        return true
      end

      #
      # Reviews the text for restricted characters.
      #
      # @param [String] text
      #   The text to check for restricted characters within.
      #
      # @return [Boolean]
      #   Specifies whether the text contains any restricted characters.
      #
      def is_restricted?(text)
        text.each_byte do |b|
          return true if @restricted_chars.include?(b)
        end

        return false
      end

      #
      # Reviews text for restricted characters.
      #
      # @param [String] text
      #   The text to review for restricted characters.
      #
      # @return [true]
      #   Specifies that the text does not contain restricted characters.
      #
      # @raise [RestrictedChar]
      #   A restricted character was found in the specified text.
      #
      def test_restricted!(text)
        found = @restricted_chars.select { |char| text.include?(char) }

        found.map! { |char| char.dump }

        unless found.empty?
          raise(RestrictedChar,"restricted characters #{found.join(', ')} was detected in #{text.dump}")
        end

        return true
      end
    end
  end
end
